namespace OFX.Aggregator.WebScraping.Implementation
{
	#region #using Directives

	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.Windows.Forms;

	using Infrastructure;

	using mshtml;

	#endregion

	internal class HtmlDocumentWrapper : IHtmlDocument,
	                                     IDisposable
	{
		private readonly HtmlDocumentManager documentManager;
		private readonly HtmlDocument htmlDocument;
		private HTMLDocumentClass htmlDomDocument;

		[DebuggerStepThrough]
		public HtmlDocumentWrapper(HTMLDocumentClass htmlDomDocument)
		{
			if (htmlDomDocument == null)
			{
				throw new ArgumentNullException("htmlDomDocument");
			}

			this.documentManager = new HtmlDocumentManager();

			this.htmlDomDocument = htmlDomDocument;
		}

		[DebuggerStepThrough]
		public HtmlDocumentWrapper(HtmlDocument htmlDocument)
		{
			if (htmlDocument == null)
			{
				throw new ArgumentNullException("htmlDocument");
			}

			this.documentManager = new HtmlDocumentManager();

			this.htmlDocument = htmlDocument;
		}

		#region Implementation of IDisposable

		/// <summary>
		/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
		/// </summary>
		/// <filterpriority>2</filterpriority>
		public void Dispose()
		{
			this.documentManager.Dispose();
		}

		#endregion

		#region Implementation of IHtmlDocument

		[DebuggerStepThrough]
		public IHtmlElement GetElementById(string id)
		{
			return this.documentManager.GetWrapper(HtmlDomDocument.getElementById(id));
		}

		[DebuggerStepThrough]
		public void InvokeScript(string scriptName, object[] args)
		{
			if (this.htmlDocument == null)
			{
				throw new InvalidOperationException();
			}

			this.htmlDocument.InvokeScript(scriptName, args);
		}

		public IList<IHtmlFrameWindow> Frames
		{
			[DebuggerStepThrough]
			get { return new HtmlFrameWindowList(HtmlDomDocument.frames, this.documentManager); }
		}

		public IHtmlElementCollection All
		{
			[DebuggerStepThrough]
			get { return this.documentManager.GetWrapper(HtmlDomDocument.all); }
		}

		#endregion

		protected internal HTMLDocumentClass HtmlDomDocument
		{
			get
			{
				if (this.htmlDomDocument == null)
				{
					this.htmlDomDocument = (HTMLDocumentClass) this.htmlDocument.DomDocument;
					if (this.htmlDomDocument == null)
					{
						throw new InvalidOperationException("Unexpected call to HtmlDomDocument property");
					}
				}
				return this.htmlDomDocument;
			}
		}
	}
}